//
// Created by Administrator on 2015/5/22.
//

#pragma once

#include <unordered_map>
#include <string>

#include "../es.h"
#include "../es_log.h"
#include "lua.hpp"
#include "lauxlib.h"

namespace esvr
{

    static int add_lua_path(lua_State* L, const char* path)
    {
        std::string set_env_msg = std::string("package.path = package.path..\"") + ";" + path + "\"";
        int ret = luaL_dostring(L, set_env_msg.c_str());
        //println("set package.path:", ret, set_env_msg);
        return 0;
    }

    static int add_lua_cpath(lua_State* L, const char* path)
    {
        std::string set_env_msg = std::string("package.cpath = package.cpath..\"") + ";" + path + "\"";
        int ret = luaL_dostring(L, set_env_msg.c_str());
        //println("set package.cpath:", ret, set_env_msg);
        return 0;
    }

    class LuaJsonHandler : public EventListener<ConnectedEvent>,
      public EventListener<ClosedEvent>, public EventListener<ReadEvent>,
      public EventListener<WriteEvent>, public Creator<LuaJsonHandler>
    {
    public:
        virtual void on_event(const ConnectedEvent* event) override
        {
            socket_t fd = event->fd();
            this->m_client_requests[fd] = "";
        }

        virtual void on_event(const ClosedEvent* event) override
        {
            socket_t fd = event->fd();
            this->m_client_requests.erase(fd);
        }

        virtual void on_event(const ReadEvent* event) override
        {
            socket_t fd = event->fd();
            const char* data = event->data();
            size_t len = event->len();
            lua_getglobal(m_lua_env, "on_json");
            lua_pushstring(m_lua_env, data);
            int ret = lua_pcall(m_lua_env, 1, 1, 0);
            const char* lua_ret_msg = lua_tostring(m_lua_env, -1);
            if(lua_ret_msg)
            {
                IOManager::get_instance().send(fd, lua_ret_msg, strlen(lua_ret_msg));// "\0" as the end of protocol.
            }
            else
            {
                //println("no return message.error request:", data);
            }
            lua_pop(m_lua_env, 1);
            //println("lua_pcall return ", ret, ", fd:", fd);
            IOManager::get_instance().force_close(fd);
        }

        virtual void on_event(const WriteEvent* event) override
        {
            //size_t len = event->len();
            //const char* data = event->data();
            //println("write", len, " data:", data);
        }

  public:
      LuaJsonHandler()
      {
          m_lua_env = luaL_newstate();
          ::luaL_openlibs(m_lua_env);
          add_lua_path(m_lua_env, "../extra/json-esvr/?.lua");
          add_lua_cpath(m_lua_env, "../extra/json-esvr/clib/?.so");
          add_lua_cpath(m_lua_env, "../extra/json-esvr/clib/?.dll");
          int ret = luaL_dofile(m_lua_env, "../extra/json-esvr/main.lua");
          if(ret != 0)
          {
            std::string msg = lua_tostring(m_lua_env, -1);
            //println("dofile return:", ret, msg);
          }
      }

      ~LuaJsonHandler()
      {
          lua_close(m_lua_env);
      }

  private:
      std::unordered_map<socket_t, std::string> m_client_requests;
      lua_State* m_lua_env;
      };


};
